import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.HashMap;

public class Database {

    static RandomAccessFile raf;
    static HashMap<Integer, Star> stars;
    final static int LENGTH = 16;

    public Database(File file) {
        stars = new HashMap<Integer, Star>();
        try {
            raf = new RandomAccessFile(file, "rwd");
            int i = 1;
            while (raf.getFilePointer() < raf.length()) stars.put(++i, new Star(i, raf.readDouble(), raf.readDouble()));
        } catch (Exception ex) {
            System.err.println(ex);
        }
    }

    public static double averageStarID() {
        return stars.values().size() / 2;
    }

    public static double averageMagnitude() {
        double avg = 0;
        for (Star s : stars.values()) avg += s.magnitude;
        return avg / stars.values().size();
    }

    public static double averagePeriod() {
        double avg = 0;
        for (Star s : stars.values()) avg += s.period;
        return avg / stars.values().size();
    }

    public static GetResponse get(GetRequest request) {
        String type = request.type;
        String compare = request.compare;
        double value = request.value;
        if (compare.equalsIgnoreCase("average"))
            if (type.equalsIgnoreCase("id")) return new GetResponse("Average ID: " + (int) averageStarID());
            else if (type.equalsIgnoreCase("magnitude")) return new GetResponse("Average magnitude: " + averageMagnitude());
            else if (type.equalsIgnoreCase("period")) return new GetResponse("Average period: " + averagePeriod());
        String output = "<table><tr><td>StarID</td><td>Magnitude</td><td>Period</td></tr>";
        if (type.equalsIgnoreCase("id") && value < 1 || value > stars.size() + 1) output = "Error: Invalid ID (next ID = " + (stars.size() + 1) + ")";
        int counter = 0;
        for (int i = 1; i <= stars.size(); i++) {
            Star star = stars.get(i);
            if ((type.equalsIgnoreCase("id") && ((compare.equals("gt") && i <= value) || (compare.equals("lt") && i >= value)))
                    || (type.equalsIgnoreCase("magnitude") && ((compare.equals("gt") && star.magnitude <= value) || (compare.equals("lt") && star.magnitude >= value)))
                    || (type.equalsIgnoreCase("period")) && ((compare.equals("gt") && star.period <= value) || (compare.equals("lt") && star.period >= value))) continue;
            output += "\n<tr><td>" + i + "</td><td>" + star.magnitude + "</td><td>" + star.period + "</td></tr>";
            counter++;
        }
        output += "</table>\n<br />Query returned " + counter + " results.";
        return new GetResponse(output);
    }

    public static PutResponse put(PutRequest request) {
        Star star = request.star;
        if (star.id <= 0 || star.magnitude <= 0 || star.magnitude <= 0 || star.id > stars.size() + 1) return new PutResponse(Status.InvalidRangeError);
        stars.put(star.id, star);
        try {
            raf.seek(LENGTH * (star.id - 1));
            raf.writeDouble(star.magnitude);
            raf.writeDouble(star.period);
        } catch (IOException ex) {
            System.err.println(ex);
            return new PutResponse(Status.WriteError);
        }
        return new PutResponse(Status.Worked);
    }
}
